'use strict';

const { resolve, join } = require('path');
const pathExists = require('path-exists');
const userHome = require('user-home');
const { gt } = require('semver');
const { red, yellow } = require('colors/safe');
const { Command } = require('commander');

const pkg = require('../package.json');
const log = require('@ysx-cli/log');
const exec = require('@ysx-cli/exec');
const { DEFAULT_CLI_HOME } = require('@ysx-cli/utils');

async function core(argv) {
  try {
    await prepare();
    registerCommand(argv);
  } catch (err) {
    log.error(err.message);
    if (process.env.LOG_LEVEL === 'verbose') {
      console.error(err);
    }
  }
}


function registerCommand(argv) {
  // 实例化传参相当于调用：program.name('ysx')
  const program = new Command(Object.keys(pkg.bin)[0]);

  // 全局options
  program
    .option('-d --debug', '开启debug模式?', false)
    .option('-tp --targetPath <path>', '指定本地调试路径?', '');

  // 注册单个命令
  program
    .usage('create [projectName] [options]')
    .command('create [projectName]')
    .description('创建项目')
    .option('-f --force', '是否强制初始化项目?', false)
    .action(exec);

  // 监听debug参数，为true时才会触发回调
  program.on('option:debug', () => {
    // const options = program.opts();
    // console.log('options', options.debug);
    process.env.LOG_LEVEL = 'verbose';
    log.level = process.env.LOG_LEVEL;
    log.verbose('verbose', red('test verbose'));
  });


  // 监听targetPath参数, 只有传了这个参数，才会触发回调
  program.on('option:targetPath', () => {
    const { targetPath } = program.opts();
    process.env.CLI_TARGET_PATH = targetPath;
  });

  // 捕获未知命令
  program.on('command:*', cmds => {
    const validCommands = program.commands.map(cmd => cmd.name());
    log.warn('未知命令', yellow(cmds[0]));
    log.notice('可用命令', validCommands.join('|'));
  });
  program.version(pkg.version).parse(argv);
  if (!program.args.length) { // 没传任何参数
    program.outputHelp();
  }
}


async function prepare() {
  checkPkgVersion();
  checkRoot();
  checkUserHome();
  checkEnv();
  await checkUpdate();
}


function checkPkgVersion() {
  log.notice('current cli version:', pkg.version);
}

function checkRoot() {
  /*
  * 管理员正在使用cli, 那么cli生成的文件以后也只有管理员能改，
  * 所以下面这个库，如果检测到是root，就会进行降级
  * ps: process.geteuid?() === 0 时，就是mac的root账户，process.geteuid在win上无效
  * */
  // 如果是v2, 要开启es module
  const rootCheck = require('root-check');
  rootCheck();
}

function checkUserHome() {
  if (!userHome || !pathExists.sync(userHome)) {
    throw new Error(red('当前用户主目录不存在'));
  }
  // console.log('userHome>>', userHome);
}

function checkEnv() {
  const dotenv = require('dotenv');
  const envPath = resolve(userHome, '.env'); // 默认读取 cwd 下的.env文件
  if (pathExists(envPath)) {
    // 会把env文件里的变量加到 process.env 上, 并返回.env文件里的内容
    dotenv.config({
      path: envPath
    });
    // console.log('env', process.env);
  }
  createDefaultConfig();
  console.log('CLI_HOME_PATH', process.env.CLI_HOME_PATH);
}

function createDefaultConfig() {
  // 设置缓存路径
  process.env.CLI_HOME_PATH = join(userHome, process.env.CLI_HOME || DEFAULT_CLI_HOME);
}


async function checkUpdate() {
  const { npmInfo, npmVersions, npmSemverVersions } = require("@ysx-cli/npm-info");
  const { name, version: currentVersion } = pkg;
  const info = await npmInfo(name);
  // info['dist-tags'].latest 最新版不能直接用，因为不能跨大版本
  const newVersion = npmSemverVersions(currentVersion, npmVersions(info))[0];
  if (newVersion && gt(newVersion, currentVersion)) {
    log.warn('更新提示', yellow(`请更新${name}, 当前版本：${currentVersion}, 可更新到：${newVersion}`));
  }
}

module.exports = core;
